﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using daSyntaxAnalyser.SyntaxTree;
using CQLQueries.SyntaxTree;

namespace CQLQueries
{
    public class QueryData
    {
        public QueryParametr SelectTypePar;
        public Type SelectType
        {
            get
            {
                return SelectTypePar.SubStrsTypes[SelectTypePar.SubStrsTypes.Length - 1];    
            }
        }

        public int IndLastParam;
        public List<QueryParametr> Params;
        public int Begin, End;
        public QueryNode КореньДерева;
        
        public QueryData()
        {
            Params = new List<QueryParametr>();
        }

        public int TestSelectType(String str)
        {
            SelectTypePar = new QueryParametr();
            return SelectTypePar.Get(null, str);
        }

        public bool AddParam(Type owner, String str1)
        {
            if ((IndLastParam = Params.FindIndex(s => s.Str == str1)) != -1)
            {
                return true;
            }
            QueryParametr param = new QueryParametr();
            param.Str = str1;
            if (param.Get(owner, str1)!=0)
            {
                return false;
            }
            else
            {
                Params.Add(param);
                IndLastParam = Params.Count - 1;
                return true;
            }
        }

        public bool GetValParams(Type seltype, Object obj1)
        {
            for (int i = 0; i < Params.Count; ++i)
            {
                object obj = GetValue(obj1, Params[i].SubStrsTypes, Params[i].SubStrs, seltype);
                if (obj == null)
                {
                    IndLastParam = i;
                    return false;
                }
                Params[i].Val = obj;
            }
            return true;
        }

        private static object GetMass<T>(Type type, object obj, string mass, string ind)
        {
            List<T> lob = type.InvokeMember(mass, BindingFlags.GetProperty, null, obj, null) as List<T>;
            return lob[Convert.ToInt32(ind)];
        }
        
        private Object GetValue(Object owner, Type[] types, string[] strs, Type type1)
        {
            //Object obj = owner;
            //Type type = type1;
            //for (int i = 0; i < types.Length; ++i)
            //{
            //    try
            //    {
            //        obj = type.InvokeMember(strs[i], BindingFlags.GetProperty, null, obj, null);
            //    }
            //    catch
            //    {
            //        return null;
            //    }
            //    type = types[i];
            //}
            //return obj;


            Object obj = owner;
            Type type = type1;
            for (int i = 0; i < types.Length; ++i)
            {
                String s = strs[i];
                int f = s.IndexOf('[');
                String index_val;
                bool ismass = false;
                String s2 = s;
                if (f != -1)
                {
                    ismass = true;
                    s2 = s.Substring(0, f);
                }

                try
                {
                    if (ismass)
                    {
                        index_val = s.Substring(f + 1, s.Length - f - 2);
                        if (types[i].Name == "FunctionVarDeclarationElement")
                            obj = GetMass<FunctionVarDeclarationElement>(type, obj, s2, index_val);
                        else if (types[i].Name == "IdElement")
                            obj = GetMass<IdElement>(type, obj, s2, index_val);
                        else obj = GetMass<object>(type, obj, s2, index_val);
                    }
                    else
                    {
                        obj = type.InvokeMember(strs[i], BindingFlags.GetProperty, null, obj, null);
                    }
                }
                catch
                {
                    return null;
                }
                type = types[i];
            }
            return obj;

        }
    }
}
